home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / mskrmsrc.zip / MSNTCP.C < prev    next >
C/C++ Source or Header  |  1991-10-24  |  48KB  |  1,955 lines

  1. /* File MSNTCP.C
  2.  * Main TCP protocol code
  3.  *
  4.  * Copyright (C) 1991, University of Waterloo.
  5.  * Copyright (C) 1991, Trustees of Columbia University in the
  6.  *  City of New York.  Permission is granted to any individual or
  7.  *  institution to use, copy, or redistribute this software as long as
  8.  *  it is not sold for profit and this copyright notice is retained.
  9.  *
  10.  * Original version created by Erick Engelke of the University of
  11.  *  Waterloo, Waterloo, Ontario, Canada.
  12.  * Adapted and modified for MS-DOS Kermit by Joe R. Doupnik, 
  13.  *  Utah State University, jrd@cc.usu.edu, jrd@usu.Bitnet.
  14.  *
  15.  * Last edit
  16.  * 6 Sept 1991
  17.  *
  18.  *  PCTCP - the true worker of Waterloo TCP
  19.  *         - contains all opens, closes, major read/write routines and
  20.  *        basic IP handler for incomming packets
  21.  *      - NOTE: much of the TCP/UDP/IP layering is done at data structure
  22.  *        level, not in separate routines or tasks
  23.  *
  24.  */
  25.  
  26. #include "msntcp.h"
  27. #include "msnlib.h"
  28. /*
  29. #define OLD 1
  30. */
  31.  
  32. static void (*system_yield)() = NULL;
  33. static tcp_Retransmitter();
  34. static tcp_unthread(void * s);
  35. static tcp_handler(void * s);
  36. static udp_handler(void * s);
  37. extern int arp_handler(in_Header *);
  38. extern int icmp_handler(void * s);
  39. int tcp_rst(in_Header *his_ip, tcp_Header *oldtcpp);
  40. static tcp_ProcessData(void *s, void * tp, int len);
  41.  
  42. static initialized = 0;
  43. longword ipbcast = 0xffffffffL;        /* default IP broadcast address */
  44. word waittime = 2;    /* tcp_sendsoon, normal ticks to wait, ~0.1 sec */
  45.  
  46. #ifdef DEBUG
  47. void (*dbugxmit)() = NULL;
  48. void (*dbugrecv)() = NULL;
  49. #endif
  50. /*
  51.  * Local IP address
  52.  */
  53.  
  54. longword my_ip_addr = 0L;    /* for external references */
  55. longword sin_mask = 0xfffffe00L;
  56. longword sin_gate = 0L;
  57.  
  58. /*
  59.  * IP identification numbers
  60.  */
  61.  
  62. static int ip_id = 0;            /* packet number */
  63. static int next_tcp_port = 1024;    /* auto incremented */
  64. static int next_udp_port = 1024;
  65. static tcp_Socket *tcp_allsocs = NULL;    /* TCP socket linked list head */
  66. static udp_Socket *udp_allsocs = NULL;    /* UDP socket linked list head */
  67.  
  68. /* Timer definitions */
  69. #define RETRAN_STRAT_TIME  1     /* ticks, how often to check retransmitter*/
  70. #define tcp_RETRANSMITTIME 3     /* interval to call retransmitter */
  71. #define tcp_LONGTIMEOUT 31       /* timeout for opens */
  72. #define tcp_TIMEOUT 13           /* timeout during a connection */
  73.  
  74. word debug_on = 0;
  75. byte *hostname = "012345678901234567890123456789012345678901234567890";
  76. word mss = ETH_MSS;
  77. word sourcequench = 0;        /* non-zero if received ICMP Source Quench */
  78.  
  79. /*
  80.  * tcp_Init - Initialize the tcp implementation
  81.  *        - may be called more than once without hurting
  82.  */
  83. int
  84. tcp_init()
  85. {
  86.     extern int arp_last_gateway;
  87.     extern int last_nameserver;
  88.     extern byte *loc_domain;
  89.     void    icmp_init();
  90.  
  91.     if (initialized != 0) return (1);    /* success, inited already */
  92.                 /* initialize ethernet interface */
  93.     arp_init();            /* clear ARP tables */
  94.     icmp_init();            /* clear ICMP material */
  95.     last_nameserver = 0;        /* reset the nameserver table */
  96.     loc_domain = NULL;        /* name server work variable */
  97.     *hostname = 0;            /* reset the host's name */
  98.     tcp_allsocs = NULL;
  99.     udp_allsocs = NULL;
  100.     ip_id = 0;
  101.     initialized = eth_init();    /* init the hardware, can fail */
  102.     if (my_ip_addr == 0L)         /* my_ap_addr is longword*/
  103.         bcopy(ð_addr[2], &my_ip_addr, 4); /* a pseudo long */
  104.     
  105.     next_udp_port = next_tcp_port = 1024 + (realclock() & 0x1ff);
  106.     eth_free (NULL);        /* clear all pkt rcv bufs */
  107.     return (initialized);        /* success (1) or failure (0) */
  108. }
  109.  
  110. /*
  111.  * Shut down the card and all services
  112.  */
  113. void
  114. tcp_shutdown()
  115. {
  116.     while (tcp_allsocs != NULL)
  117.         tcp_abort(tcp_allsocs);
  118.     eth_release();
  119.     initialized = 0;
  120. }
  121.  
  122. int 
  123. udp_open(s, lport, ina, port, datahandler)
  124. udp_Socket *s;
  125. longword ina;
  126. word lport, port;
  127. procref datahandler;
  128. {
  129.     if (s == NULL) return (0);
  130.  
  131.     memset(s, 0, sizeof(udp_Socket));
  132.     s->ip_type = UDP_PROTO;
  133.     if (lport == 0) lport = ++next_udp_port;  /* get a nonzero port val */
  134.     s->myport = lport;
  135.  
  136.     /* check for broadcast */
  137.     if (ina == 0xffffffffL || ina == 0L || ina == ipbcast)
  138.         memset(s->hisethaddr, 0xff, sizeof(eth_address));
  139.     else
  140.         if (arp_resolve(ina, &s->hisethaddr[0]) == 0)
  141.             return (0);
  142.     s->hisaddr = ina;
  143.     s->hisport = port;
  144.     s->dataHandler = datahandler;
  145.     s->usr_yield = system_yield;
  146.     s->next = udp_allsocs;
  147.     udp_allsocs = s;
  148.     return (1);
  149. }
  150.  
  151. /*
  152.  * Actively open a TCP connection to a particular destination.
  153.  *    - 0 on error
  154.  */
  155. int 
  156. tcp_open(s, lport, ina, port, datahandler)
  157. tcp_Socket *s;
  158. longword ina;
  159. word lport, port;
  160. procref datahandler;
  161. {
  162.     if (s == NULL) return (0);
  163.  
  164.     memset(s, 0, sizeof(tcp_Socket));    /* zero everything */
  165.     s->ip_type = TCP_PROTO;
  166.     s->mss = mss;
  167.     s->state = tcp_StateSYNSENT;
  168.     s->timeout = set_timeout(tcp_LONGTIMEOUT);
  169.     s->rmaxdatalen = tcp_MaxBufSize;
  170.     s->cwindow = 1;            /* slow start VJ algorithm */
  171.     s->vj_sa = 4;            /* about 250 ms (4/18.2 tics/sec) */
  172.     if (lport == 0)
  173.         lport = ++next_tcp_port;  /* get a nonzero port value */
  174.     s->myport = lport;
  175.     if (! arp_resolve(ina, &s->hisethaddr[0]))
  176.         return (0);
  177.     s->hisaddr = ina;
  178.     s->hisport = port;
  179.     s->seqnum = intel(set_timeout(0)) & 0xffff0000;
  180.     s->datalen = 0;
  181.     s->flags = tcp_FlagSYN;
  182.     s->unhappy = TRUE;
  183.     s->dataHandler = datahandler;
  184.     s->usr_yield = system_yield;
  185.     s->next = tcp_allsocs;
  186.     s->rtt_delay = s->rtt_smooth = 18;    /* one second startup */
  187.     tcp_allsocs = s;
  188.     return (tcp_send(s));        /* fail if send fails */
  189. }
  190.  
  191. /*
  192.  * Passive open: listen for a connection on a particular port
  193.  */
  194. tcp_listen(s, lport, ina, port, datahandler, timeout)
  195. tcp_Socket *s;
  196. word port, lport, timeout;
  197. longword ina;
  198. procref datahandler;
  199. {
  200.     if (s == NULL) return (0);
  201.  
  202.     memset(s, 0, sizeof(tcp_Socket));
  203.     s->ip_type = TCP_PROTO;
  204.     s->mss = mss;
  205.     s->rmaxdatalen = tcp_MaxBufSize;
  206.     s->cwindow = 1;            /* slow start VJ algorithm */
  207.     s->vj_sa = 4;            /* about 250 ms */
  208.     s->state = tcp_StateLISTEN;
  209.     if (timeout == 0)
  210.         s->timeout = 0;         /* no timeout */
  211.     else
  212.         s->timeout = set_timeout(timeout);
  213.     s->myport = lport;
  214.     s->hisport = port;
  215.     s->hisaddr = ina;
  216.     s->seqnum = intel(set_timeout(0)) & 0xffff0000;
  217.     s->datalen = 0;
  218.     s->flags = 0;
  219.     s->unhappy = FALSE;
  220.     s->dataHandler = datahandler;
  221.     s->usr_yield = system_yield;
  222.     s->next = tcp_allsocs;
  223.     tcp_allsocs = s;
  224.     return (1);
  225. }
  226.  
  227.  
  228. static int
  229. udp_close(ds)
  230. udp_Socket *ds;
  231. {
  232.     register udp_Socket *sp;
  233.  
  234.     sp = udp_allsocs;        /* ptr to first socket */
  235.     if (sp == NULL) return (0);    /* failure */
  236.     if (sp == ds) udp_allsocs = ds->next; /* if we are first, unlink */
  237.     while (sp != NULL)
  238.         {
  239.         if (sp->next == ds)    /* if current points to us */
  240.             {
  241.             sp->next = ds->next; /* point it to our successor */
  242.                break;
  243.             }
  244.         sp = sp->next;        /* look at next socket */
  245.         }
  246.     return (1);            /* success */
  247. }
  248.  
  249. /*
  250.  * Send a FIN on a particular port -- only works if it is open
  251.  * Must still allow receives
  252.  * Returns 0 for failure
  253.  */
  254. static 
  255. tcp_close(s)
  256. tcp_Socket *s;
  257. {
  258.     if (s == NULL) return (0);
  259.     if (s->ip_type != TCP_PROTO)
  260.         return (0);            /* failure */
  261.     if (s->state == tcp_StateESTAB || s->state == tcp_StateSYNREC)
  262.         {
  263.         if (s->err_msg == NULL)
  264.             s->err_msg = "TCP_Closed called";
  265.         s->flags = tcp_FlagACK | tcp_FlagFIN;
  266.         if (s->datalen)
  267.             s->flags |= tcp_FlagPUSH;
  268.         s->state = tcp_StateFINWT1;
  269.         s->timeout = set_timeout(4);
  270.                     /* should be a pretty lengthy time */
  271.         s->unhappy = TRUE;
  272.         tcp_send(s);
  273.         return (1);            /* success */
  274.         }
  275.     return (0);
  276. }
  277.  
  278. /*
  279.  * Abort a tcp connection
  280.  * Returns 0 if failure
  281.  */
  282. static int 
  283. tcp_abort(s)
  284. tcp_Socket *s;
  285. {
  286.     if (s == NULL) return (0);        /* failure */
  287.  
  288.     if (s->err_msg == NULL) s->err_msg = "TCP_ABORT";
  289.     if ((s->state != tcp_StateLISTEN) && (s->state != tcp_StateCLOSED))
  290.         {
  291.         s->flags = tcp_FlagRST | tcp_FlagACK;
  292.         s->unhappy = TRUE;
  293.         tcp_send(s);
  294.         }
  295.     s->unhappy = FALSE;
  296.     s->datalen = 0;
  297.     s->state = tcp_StateCLOSED;
  298.     if (s->dataHandler) s->dataHandler(s, 0, -1);
  299.     tcp_unthread(s);
  300.     return (1);                /* success */
  301. }
  302.  
  303. void 
  304. sock_abort(s)
  305. tcp_Socket *s;
  306. {
  307.     if (s == NULL) return;            /* do nothing */
  308.     if (s->ip_type == TCP_PROTO)
  309.         tcp_abort(s);
  310.     else
  311.         udp_close(s);
  312. }
  313.  
  314. /*
  315.  * tcp_sendsoon - schedule a transmission pretty soon
  316.  *        - this one has an imperfection at midnight, but it
  317.  *          is not significant to the connection performance
  318.  * Return 0 if failure.
  319.  */
  320. tcp_sendsoon(s)
  321. tcp_Socket *s;
  322. {
  323.     longword temp;
  324.  
  325.     if (s == NULL) return (0);
  326.  
  327.     if (s->ip_type != TCP_PROTO) return (0);
  328.  
  329.     s->karn_count = 1;
  330.     if (sourcequench != 0)            /* ICMP shutup message */
  331.         {
  332.         waittime += waittime;        /* double the timeout */
  333.         sourcequench = 0;        /* forget the reminder */
  334.         }
  335.  
  336.     temp = set_ttimeout(waittime);        /* Bios ticks into the future */
  337.     if ((s->rtt_time < temp))        /* if now is too soon */
  338.         return (1);            /* then wait some more */
  339.     if (waittime > 2)            /* if backing off already */
  340.         waittime = (waittime * 15) / 16; /* recover slowly */
  341.     s->rtt_time = temp;
  342.     return (1);
  343. }
  344.  
  345. /*
  346.  * Retransmitter - called periodically to perform tcp retransmissions
  347.  * Returns 0 if failure
  348.  */
  349. static 
  350. tcp_Retransmitter()
  351. {
  352.     register tcp_Socket *s;
  353.     static longword retran_strat = 0L;    /* timeout retran strategy */
  354.  
  355.             /* do this only once per RETRAN_STRAT_TIME clock ticks */
  356.     if (!chk_timeout(retran_strat))
  357.         return (0L);
  358.     retran_strat = set_ttimeout(RETRAN_STRAT_TIME);
  359.  
  360.     for (s = tcp_allsocs; s != NULL; s = s->next)
  361.         {
  362.         if ((s->datalen > 0) ||    (s->unhappy == TRUE) ||
  363.                 (s->karn_count == 1))
  364.                             /* retransmission strategy */
  365.                 if (chk_timeout(s->rtt_time)) /* if timeout */
  366.                 {
  367.                 if (s->karn_count == 0)
  368.                             s->karn_count = 2;
  369.                         /* if really did timeout */
  370.                         tcp_send(s);
  371.                     }
  372.  
  373.         if (s->timeout && chk_timeout(s->timeout))
  374.             {
  375.             if (s->state == tcp_StateTIMEWT)
  376.                 {
  377.                 s->flags = tcp_FlagACK;
  378.                 s->state = tcp_StateCLOSED;
  379.                 }
  380.             else if (s->state != tcp_StateESTAB)
  381.                 {
  382.                 s->err_msg = "Timeout, aborting";
  383.                 tcp_abort(s);
  384.                 }
  385.             }
  386.         }
  387.     return (1);        /* success */
  388. }
  389.  
  390. /*
  391.  * Unthread a socket from the socket list, if it's there. Return 0 on failure
  392.  */
  393. static int
  394. tcp_unthread(ds)
  395. tcp_Socket *ds;
  396. {
  397.     register tcp_Socket *sp;
  398.  
  399.     if (ds == NULL) return (0);        /* failure */
  400.  
  401.     if ((ds->rdatalen == 0) || (ds->state > tcp_StateESTAB))
  402.         ds->ip_type = 0;        /* fail io */
  403.     ds->state = tcp_StateCLOSED;           /* tcp_tick needs this */
  404.     if (tcp_allsocs == NULL) return (0);
  405.  
  406.     sp = tcp_allsocs;            /* ptr to first socket */
  407.     if (sp == ds) tcp_allsocs = ds->next; /* if we are first, unlink */
  408.     while (sp != NULL)
  409.         {
  410.         if (sp->next == ds)        /* if current points to us */
  411.             {
  412.             sp->next = ds->next; /* point it to our successor */
  413.                break;
  414.             }
  415.         sp = sp->next;            /* look at next socket */
  416.         }
  417.     return (1);                /* success */
  418. }
  419.  
  420. /*
  421.  * tcp_tick - called periodically by user application
  422.  *        - returns 0 when our socket closes
  423.  *        - called with socket parameter or NULL
  424.  */
  425. tcp_tick(s)
  426. sock_type *s;
  427. {
  428.     register in_Header *ip;
  429.     int packettype;
  430.  
  431.                 /* finish off dead sockets */
  432.     if (s != NULL)
  433.         if (s->tcp.ip_type == TCP_PROTO &&
  434.          s->tcp.state == tcp_StateCLOSED)
  435.              s->tcp.ip_type = 0;
  436.  
  437.                     /* read a packet */
  438.     while ((ip = (in_Header *)eth_arrived(&packettype)) != NULL)
  439.     {
  440.  
  441.     switch (intel16(packettype))      /* big to little endian form */
  442.     {
  443.     case 0x0800:                /* do IP */
  444.         if (checksum(ip, in_GetHdrlenBytes(ip)) != 0xffff)
  445.             {
  446.             if (debug_on)
  447.                 outs("IP Received BAD Checksum \n\r");
  448.             break;
  449.             }
  450.         if ((my_ip_addr == 0L) || 
  451.             (intel(ip->destination)    == my_ip_addr))
  452.             {
  453.             switch (ip->proto)
  454.                 {
  455.                 case TCP_PROTO:
  456.                     tcp_handler(ip);
  457.                     break;
  458.                 case UDP_PROTO:
  459.                     udp_handler(ip);
  460.                     break;
  461.                 case ICMP_PROTO:
  462.                     icmp_handler(ip);
  463.                     break;
  464.                 default:
  465.                     break;
  466.                 }    /* end of switch (ip->proto) */
  467.             }
  468.         break;
  469.  
  470.     case 0x0806:                /* do ARP */
  471.         arp_handler(ip);
  472.         break;
  473.     case 0x8035:                /* do RARP */
  474.         rarp_handler(ip);
  475.         break;
  476.     default:                /* unknown type */
  477.         break;
  478.     }                /* end of switch */
  479.     eth_free(ip);            /* free the processed packet */
  480.     }                    /* end of while */
  481.  
  482.     tcp_Retransmitter();        /* check on pending sends */
  483.     return ((s != NULL)? s->tcp.ip_type: 0); /* 0 means closed socket */
  484. }
  485.  
  486. void
  487. tcp_set_debug_state(x)
  488. word x;
  489. {
  490.     debug_on = x;
  491. }
  492.  
  493. /* returns 1 if connection is established, else 0 */
  494. int 
  495. tcp_established(s)
  496. tcp_Socket *s;
  497. {
  498.     if (s == NULL) return (0);        /* failure */
  499.     return (s->state == tcp_StateESTAB);
  500. }
  501.  
  502.  
  503. static int
  504. udp_Write(s, datap, len)
  505. udp_Socket *s;
  506. byte *datap;
  507. int len;
  508. {
  509.     tcp_PseudoHeader ph;
  510.     struct pkt
  511.         {
  512.         in_Header  in;
  513.         udp_Header udp;
  514.         int       data;
  515. /*        longword maxsegopt; */
  516.         } register *pkt;
  517.  
  518.     if (s == NULL || datap == NULL)
  519.         return (0);            /* failure */
  520.  
  521.     pkt = (struct pkt *)eth_formatpacket(&s->hisethaddr[0], 0x0008);
  522.     pkt->in.length = intel16(sizeof(in_Header) + UDP_LENGTH + len);
  523.  
  524.                         /* UDP header */
  525.     pkt->udp.srcPort = intel16(s->myport);
  526.     pkt->udp.dstPort = intel16(s->hisport);
  527.     pkt->udp.checksum = 0;
  528.     pkt->udp.length = intel16(UDP_LENGTH + len);
  529.     bcopy(datap, &pkt->data, len);
  530.                         /* Internet header */
  531.     pkt->in.hdrlen_ver = 0x45;        /* version 4, hdrlen 5 */
  532.     pkt->in.tos = 0;
  533.     pkt->in.identification = intel16(++ip_id);    /* was post inc */
  534.     pkt->in.frag = 0;
  535. #ifdef KERMIT
  536.     pkt->in.ttl = 60;
  537. #else
  538.     pkt->in.ttl = 254;
  539. #endif
  540.     pkt->in.proto = UDP_PROTO;            /* UDP */
  541. /*    inp->ttlProtocol = (250<<8) + 6; */
  542.     pkt->in.checksum = 0;
  543.     pkt->in.source = intel(my_ip_addr);
  544.     pkt->in.destination = intel(s->hisaddr);
  545.     pkt->in.checksum = ~checksum(&pkt->in, sizeof(in_Header));
  546.                     /* compute udp checksum if desired */
  547.     if (s->soc_mode & UDP_MODE_NOCHK)
  548.         pkt->udp.checksum = 0;
  549.     else
  550.         {
  551.         ph.src = pkt->in.source;        /* big endian now */
  552.         ph.dst = pkt->in.destination;
  553.         ph.mbz = 0;
  554.         ph.protocol = UDP_PROTO;        /* UDP */
  555.         ph.length = pkt->udp.length;        /* big endian now */
  556.         ph.checksum = checksum(&pkt->udp, intel16(ph.length));
  557.         pkt->udp.checksum = ~checksum(&ph, sizeof(ph));
  558.         }
  559.  
  560. #ifdef DEBUG
  561.     if (dbugxmit) (*dbugxmit)(s,inp,udpp);
  562. #endif
  563.     if (eth_send(intel16(pkt->in.length)) != 0)    /* send pkt */
  564.         return (len);
  565.     else    return (0);                /* failed */
  566. }
  567.  
  568. /*
  569.  * udp_read - read data from buffer, does large buffering.
  570.  * Return 0 on failure.
  571.  */
  572. static int 
  573. udp_read(s, datap, maxlen)
  574. udp_Socket *s;
  575. byte *datap;
  576. int maxlen;
  577. {
  578.     register int x;
  579.  
  580.     if (s == NULL || datap == NULL) return (0);        /* failure */
  581.     if ((x = s->rdatalen) > 0)
  582.         {
  583.         if (x > maxlen) x = maxlen;
  584.         if (x > 0)
  585.             {
  586.             bcopy(s->rdata, datap, x);
  587.             if (s->rdatalen -= x)
  588.                 bcopy(&s->rdata[x], s->rdata, s->rdatalen);
  589.             }
  590.             }
  591.     return (x);
  592. }
  593.  
  594. udp_cancel(in_Header *ip)
  595. {
  596.     int len;
  597.     register udp_Header *up;
  598.     register udp_Socket *s;
  599.  
  600.                         /* match to a udp socket */
  601.     len = in_GetHdrlenBytes(ip);
  602.     up = (udp_Header *)((byte *)ip + len);    /* udp frame pointer */
  603.  
  604.                         /* demux to active sockets */
  605.     for (s = udp_allsocs; s != NULL; s = s->next)
  606.             if (s->hisport != 0 &&
  607.              intel16(up->dstPort) == s->myport &&
  608.              intel16(up->srcPort) == s->hisport &&
  609.              intel(ip->source) == s->hisaddr)
  610.                  break;
  611.  
  612.     if (s == NULL)                /* demux to passive sockets */
  613.         for (s = udp_allsocs; s != NULL; s = s->next)
  614.                 if (s->hisport == 0 && 
  615.                 intel16(up->dstPort) == s->myport)
  616.                     break;
  617.  
  618.     if (s != NULL)
  619.         {
  620.             s->rdatalen = 0;
  621.         s->ip_type = 0;
  622.         }
  623.     return (1);                /* success */
  624. }
  625.  
  626. int
  627. tcp_cancel(in_Header *ip)
  628. {
  629.     int len;
  630.     register tcp_Socket *s;
  631.     register tcp_Header *tp;
  632.  
  633.     if (ip == NULL) return (0);        /* failure */
  634.     len = in_GetHdrlenBytes(ip);        /* check work */
  635.  
  636.     tp = (tcp_Header *)((byte *)ip + len);    /* TCP frame pointer */
  637.  
  638.                         /* demux to active sockets */
  639.     for (s = tcp_allsocs; s != NULL; s = s->next)
  640.             if (s->hisport != 0 &&
  641.              intel16(tp->dstPort) == s->myport &&
  642.              intel16(tp->srcPort) == s->hisport &&
  643.              intel(ip->source) == s->hisaddr)
  644.                  break;
  645.  
  646.     if (s == NULL)            /* demux to passive sockets */
  647.         for (s = tcp_allsocs; s != NULL; s = s->next)
  648.                 if (s->hisport == 0 &&
  649.                 intel16(tp->dstPort) == s->myport)
  650.                     break;
  651.     if (s != NULL)
  652.         {
  653.         s->rdatalen = 0;
  654.         s->state = tcp_StateCLOSED;
  655.             s->ip_type = 0;
  656.         if (s->dataHandler) s->dataHandler(s, 0, -1);
  657.         tcp_unthread(s);
  658.         }
  659.     return (1);                /* success */
  660. }
  661.  
  662. static int 
  663. tcp_read(s, datap, maxlen)
  664. tcp_Socket *s;
  665. byte *datap;
  666. int maxlen;
  667. {
  668.     register int x;
  669.  
  670.     if (s == NULL || datap == NULL || maxlen == 0)
  671.             return (0);        /* failure or read nothing */
  672.     if ((x = s->rdatalen) > 0)
  673.         {
  674.         if (x > maxlen) x = maxlen;
  675.         bcopy(s->rdata, datap, x);    /* copy out desired data */
  676.         if ((s->rdatalen -= x) < 0)
  677.             s->rdatalen = 0;    /* readjust socket buf */
  678.         bcopy(&s->rdata[x], s->rdata, s->rdatalen);
  679.         tcp_sendsoon(s);        /* update the window */
  680.         }
  681.     return (x);                /* return bytes read */
  682. }
  683.  
  684. /*
  685.  * Write data to a connection.
  686.  * Returns number of bytes written, == 0 when connection is not in
  687.  * established state.
  688.  */
  689. static int
  690. tcp_Write(s, dp, len)
  691. tcp_Socket *s;
  692. byte *dp;
  693. int len;
  694. {
  695.     register int x;
  696.  
  697.     if (s == NULL || dp == NULL) return (0);    /* failure */
  698.     if (s->state != tcp_StateESTAB) len = 0;
  699.     if (len > (x = tcp_MaxBufSize - s->datalen)) len = x;
  700.     if (len > 0)
  701.         {
  702.         bcopy(dp, &s->data[s->datalen], len);
  703.         s->datalen += len;
  704.         s->unhappy = TRUE;/* redundant because of outstanding data */
  705.  
  706.         if (s->soc_mode & TCP_MODE_NONAGLE)
  707.             tcp_send(s);
  708.         else    /* transmit if first data or reached MTU */
  709.                 /* not true MTU, but better than nothing */
  710.                 if ((s->datalen == len) || (s->datalen > (s->mss)))
  711.                 tcp_send(s);
  712.         }
  713.     return (len);
  714. }
  715.  
  716. /*
  717.  * Send pending data
  718.  */
  719. static int
  720. tcp_Flush(s)
  721.     tcp_Socket *s;
  722. {
  723.     if (s == NULL) return (0);        /* failure */
  724.     if (s->datalen > 0)
  725.         {
  726.             s->flags |= tcp_FlagPUSH;
  727.         tcp_send(s);
  728.             }
  729.     return (1);                    /* success */
  730. }
  731.  
  732. /*
  733.  * Handler for incoming UDP packets. Return 0 if no socket.
  734.  */
  735. static int
  736. udp_handler(ip)
  737. in_Header *ip;
  738. {
  739.     register udp_Header *up;
  740.     register udp_Socket *s;
  741.     tcp_PseudoHeader ph;
  742.     byte *dp;
  743.     word len;
  744.  
  745.     len = in_GetHdrlenBytes(ip);
  746.     up = (udp_Header *)((byte *)ip + len);    /* UDP segment pointer */
  747.     len = intel16(up->length);
  748.  
  749.                 /* demux to active sockets */
  750.     for (s = udp_allsocs; s != NULL; s = s->next)
  751.         if (s->hisport != 0 &&
  752.             intel16(up->dstPort) == s->myport &&
  753.             intel16(up->srcPort) == s->hisport &&
  754.             intel(ip->source) == s->hisaddr)
  755.                 break;
  756. #ifdef DEBUG
  757.     if (dbugrecv) (*dbugrecv)(s,ip,up);
  758. #endif
  759.  
  760.     if (s == NULL)            /* demux to passive sockets */
  761.         for (s = udp_allsocs; s != NULL; s = s->next)
  762.             if (s->hisaddr == 0 && 
  763.                 intel16(up->dstPort) == s->myport)
  764.                 {
  765.                 if (arp_resolve(intel(ip->source),
  766.                     &s->hisethaddr[0]))
  767.                     {
  768.                        s->hisaddr = intel(ip->source);
  769.                         s->hisport = intel16(up->srcPort);
  770.                     }
  771.                 break;
  772.                     }
  773.  
  774.     if (s == NULL)        /* demux to broadcast sockets */
  775.         for (s = udp_allsocs; s != NULL; s = s->next)
  776.             if (s->hisaddr == ipbcast && 
  777.                 intel16(up->dstPort) == s->myport)
  778.                     break;
  779.  
  780.     if (s == NULL)
  781.         {
  782.         if (debug_on) outs("discarding...");
  783.         return (0);            /* say no socket */
  784.         }
  785.  
  786.     if (up->checksum)
  787.         {
  788.         ph.src = ip->source;        /* already bigend'd */
  789.         ph.dst = ip->destination;
  790.         ph.mbz = 0;
  791.         ph.protocol = UDP_PROTO;
  792.         ph.length = up->length;
  793.         ph.checksum = checksum(up, len);
  794.         if (checksum(&ph, sizeof(tcp_PseudoHeader)) != 0xffff)
  795.             return (0);        /* failure */
  796.         }
  797.  
  798.                         /* process user data */
  799.     if ((len -= UDP_LENGTH) > 0)
  800.         {
  801.         dp = (byte *)(up);
  802.         if (s->dataHandler != NULL)
  803.             s->dataHandler(s, &dp[UDP_LENGTH], len, &ph);
  804.         else
  805.             {
  806.             if (len > udp_MaxBufSize) len = udp_MaxBufSize;
  807.             bcopy(&dp[UDP_LENGTH], s->rdata, len);
  808.             s->rdatalen = len;
  809.             }
  810.         }
  811.     return (1);                /* success */
  812. }
  813.  
  814. /* Handle TCP packets. Return 0 if no socket. */
  815.  
  816. static 
  817. tcp_handler(ip)
  818. in_Header *ip;
  819. {
  820.     register tcp_Header *tp;
  821.     tcp_PseudoHeader ph;
  822.     int len;
  823.     int diff;                /* signed, please */
  824.     register tcp_Socket *s;
  825.     word flags;
  826.     long diffticks, ldiff;            /* must be signed */
  827.  
  828.  
  829.     len = in_GetHdrlenBytes(ip);
  830.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  831.     len = intel16(ip->length) - len;    /* len of tcp data */
  832.     flags = intel16(tp->flags);
  833.  
  834.                 /* demux to active sockets */
  835.     for (s = tcp_allsocs; s != NULL; s = s->next)
  836.         if (s->hisport != 0 &&
  837.             intel16(tp->dstPort) == s->myport &&
  838.             intel16(tp->srcPort) == s->hisport &&
  839.             intel(ip->source) == s->hisaddr)
  840.             break;
  841.  
  842.     if (s == NULL)    /* demux to passive sockets, must be a new session */
  843.         for (s = tcp_allsocs; s != NULL; s = s->next)
  844.             if ((s->hisport == 0) &&
  845.                 (intel16(tp->dstPort) == s->myport))
  846.                 break;
  847.  
  848. #ifdef DEBUG
  849.     if (dbugrecv) (*dbugrecv)(s, ip, tp);
  850. #endif
  851.  
  852.     if (s == NULL)
  853.         {
  854.          /* no session seems to exist, nor is there desire to start 
  855.          one, so we must send a reset    */
  856.         tcp_rst(ip, tp);
  857.         return (0);        /* 0 to say socket is closed */
  858.         }
  859.  
  860.                 /* save his ethernet address */
  861.     bcopy(&((((eth_Header *)ip) - 1)->source[0]), &s->hisethaddr[0],
  862.             sizeof(eth_address));
  863.  
  864.     ph.src = ip->source;            /* network order now */
  865.     ph.dst = ip->destination;
  866.     ph.mbz = 0;
  867.     ph.protocol = TCP_PROTO;
  868.     ph.length = intel16(len);
  869.     ph.checksum =  checksum(tp, len);
  870.     if (checksum(&ph, sizeof(ph)) != 0xffff)
  871.         {
  872.          if (debug_on) outs("bad tcp checksum \n\r");
  873.          return (1);
  874.         }
  875.  
  876.                     /* reset code */
  877.     if (flags & tcp_FlagRST)
  878.         {
  879.         if (debug_on) outs("\7\7connection reset\n");
  880.         s->rdatalen = 0;
  881.         s->state = tcp_StateCLOSED;
  882.         if (s->dataHandler) s->dataHandler(s, 0, -1);
  883.         tcp_unthread(s);
  884.         return (0);            /* say socket is closed */
  885.         }
  886.  
  887.                     /* update our retransmission stuff */
  888.     if (s->karn_count == 2)
  889.         {
  890.                         /* use the backed off rto */
  891.          }
  892.     else if ((diffticks = set_ttimeout(0) - s->vj_last) >= 0)
  893.         {                /* we ignore the overnight case */
  894.         diffticks -= (s->vj_sa >> 3);
  895.         s->vj_sa += (word)diffticks;
  896.         if (diffticks < 0)
  897.             diffticks = -diffticks;
  898.         diffticks -= (s->vj_sd >> 2);
  899.         s->vj_sd += diffticks;
  900.         s->rto = ((s->vj_sa >> 2) + s->vj_sd) >> 1;
  901.         s->karn_count = 0;
  902.         }
  903.  
  904.     if (flags & tcp_FlagRST)
  905.         {
  906.                     /* we must listen to resync */
  907.         }
  908.  
  909.     switch (s->state) {
  910.  
  911.     case tcp_StateLISTEN:    /* accepting SYNs */
  912.         if (flags & tcp_FlagSYN)
  913.         {
  914.         s->acknum = intel(tp->seqnum) + 1;
  915.         s->hisport = intel16(tp->srcPort);
  916.         s->hisaddr = intel(ip->source);
  917.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  918.         tcp_send(s);        /* we must respond immediately */
  919.         s->state = tcp_StateSYNREC;
  920.             s->unhappy = FALSE;
  921.         s->timeout = set_timeout(tcp_TIMEOUT);
  922.         }
  923.     else
  924.             tcp_rst(ip, tp);  /* send a reset */
  925.         break;
  926.  
  927.     case tcp_StateSYNSENT:        /* added ACK Section */
  928.     if (flags & tcp_FlagSYN)
  929.         {
  930.             s->flags = tcp_FlagACK;
  931.         s->timeout = set_timeout(tcp_TIMEOUT);
  932.  
  933.         /* FlagACK means connection established, else SYNREC */
  934.         if (flags & tcp_FlagACK)
  935.             {      /* but is it for the correct session? */
  936.             if (tp->acknum == intel(s->seqnum + 1))
  937.                 {
  938.                 s->state = tcp_StateESTAB;
  939.                 s->seqnum++;        /* good increment */
  940.                 s->acknum = intel(tp->seqnum) + 1; /*32 bits*/
  941.                 s->unhappy = TRUE;
  942.                 tcp_ProcessData(s, tp, len);
  943.                 }
  944.             else
  945.                 { /* wrong ack, force a RST and resend SYN*/
  946.                 s->flags = tcp_FlagRST;
  947.                 s->unhappy = TRUE;
  948.                 tcp_send(s);
  949.                 s->unhappy = FALSE; /* no need to retransmit */
  950.                 s->flags = tcp_FlagSYN;
  951.                 tcp_send(s);
  952.                 }
  953.             }
  954.         else
  955.             {
  956.             s->acknum++;
  957.             s->state = tcp_StateSYNREC;
  958.             /* maybe check sequence number stuff too */
  959.             }
  960.         }
  961.     break;
  962.  
  963.     case tcp_StateSYNREC:    /* recSYNSENT, sentACK, waiting EST */
  964.     if (flags & tcp_FlagSYN)
  965.         {
  966.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  967.             tcp_send(s);
  968.         s->timeout = set_timeout(tcp_TIMEOUT);
  969.         }
  970.     if ((flags & tcp_FlagACK) && (intel(tp->acknum) == (s->seqnum + 1)))
  971.         {
  972.         s->flags = tcp_FlagACK;
  973.         tcp_send(s);
  974.         s->seqnum++;
  975.         s->unhappy = FALSE;
  976.         s->state = tcp_StateESTAB;
  977.             s->timeout = 0;             /* never timeout */
  978.         tcp_ProcessData(s, tp, len);
  979.         }
  980.     break;
  981.  
  982.     case tcp_StateESTAB:
  983.     if ((flags & tcp_FlagACK) == 0) return (1); /* they must ack somthing*/
  984.  
  985.     s->timeout = 0L;    /* we do not timeout at this point */
  986.                 /* process their ack value in packet */
  987.     /* If their ack preceeds the window this is an old pkt. */
  988.     /* If ack exceeds the window then they are lying, don't believe. */
  989.     /* However, in all cases grab any useful data for us. */        
  990.     ldiff = intel(tp->acknum) - s->seqnum; /* current - prev ack */
  991.     if (ldiff >= 0 && ldiff <= s->datalen)
  992.         {             /* their ack is in our window*/
  993.         s->seqnum += ldiff;    /* update ACK'd file pointer */
  994.         diff = ldiff;        /* 16 bits, bigger than our window */
  995.         s->datalen -= diff;    /* deduct amount ACK'd */
  996.                     /* move down residual in send buf */
  997.          bcopy(&s->data[diff], s->data, s->datalen);
  998.         }
  999.     s->flags = tcp_FlagACK;        /* tell them thanks */
  1000.     tcp_ProcessData(s, tp, len);    /* process our data in the packet */
  1001.     if (ldiff != 0 || len != 0)
  1002.         tcp_sendsoon(s);
  1003.     break;
  1004.  
  1005.     case tcp_StateFINWT1:
  1006.                     /* process ack value in packet */
  1007.     ldiff = intel(tp->acknum) - s->seqnum; /* current - prev ack */
  1008.     if (ldiff >= 0 && ldiff <= s->datalen) /* their ack is in our window*/
  1009.         {
  1010.         s->seqnum += ldiff;    /* update ACK'd file counter */
  1011.         diff = ldiff;        /* 16 bits, more than our window */
  1012.         s->datalen -= diff;    /* deduct amount ACK'd */
  1013.         bcopy(&s->data[diff], s->data, s->datalen); /* move residual */
  1014.         }
  1015.     tcp_ProcessData(s, tp, len);    /* process our data in the packet */
  1016.  
  1017.     if (flags & tcp_FlagFIN)    /* trying to do simultaneous close */
  1018.         {
  1019.         if ((intel(tp->acknum) >= s->seqnum + 1) &&
  1020.             (intel(tp->seqnum) == s->acknum))
  1021.             {        /* other guy wishes to close too */
  1022.             s->seqnum++;
  1023.             s->acknum++;
  1024.             s->flags = tcp_FlagACK;
  1025.             s->unhappy = TRUE;
  1026.             s->timeout = set_timeout(3);
  1027.             s->state = tcp_StateCLOSING;
  1028.             }
  1029.         }
  1030.     else if (flags & tcp_FlagACK)
  1031.                    /* other side is legitimately acking our fin */
  1032.         if ((intel(tp->acknum) == s->seqnum + 1) &&
  1033.             (intel(tp->seqnum) == s->acknum) &&
  1034.             (s->datalen == 0))
  1035.             {
  1036.             s->seqnum++;
  1037.             s->datalen = 0;
  1038.             s->state = tcp_StateFINWT2;
  1039.                 s->timeout = set_timeout(3);
  1040.             s->unhappy = FALSE;
  1041.             }
  1042.     break;
  1043.  
  1044.     case tcp_StateFINWT2:
  1045.     if ((flags & (tcp_FlagACK | tcp_FlagFIN)) ==
  1046.         (tcp_FlagACK | tcp_FlagFIN))
  1047.         if ((intel(tp->acknum) == s->seqnum) &&
  1048.             (intel(tp->seqnum) == s->acknum))
  1049.             {
  1050.             s->acknum++;
  1051.             s->flags = tcp_FlagACK;
  1052.             tcp_send(s);
  1053.             s->unhappy = FALSE;
  1054.             s->timeout = set_timeout(2); /* max seg life 2 sec */
  1055.             s->state = tcp_StateTIMEWT;
  1056.             }
  1057.     break;
  1058.  
  1059.     case tcp_StateCLOSING:
  1060.         if ((flags & (tcp_FlagACK | tcp_FlagFIN)) == tcp_FlagACK)
  1061.         if ((tp->acknum == intel(s->seqnum)) &&
  1062.             (tp->seqnum == intel(s->acknum))) /* all agree */
  1063.         {
  1064.         s->state = tcp_StateTIMEWT;
  1065.         s->timeout = set_timeout(tcp_TIMEOUT);
  1066.         s->unhappy = FALSE;        /* no more retransmissions */
  1067.         }
  1068.     break;
  1069.  
  1070.     case tcp_StateLASTACK:
  1071.     if (flags & tcp_FlagFIN)    /* they lost our two packets, back up */
  1072.         {
  1073.         s->flags = tcp_FlagACK;
  1074.         tcp_send(s);
  1075.         s->flags = tcp_FlagACK | tcp_FlagFIN;
  1076.         tcp_send(s);
  1077.         s->unhappy = FALSE;
  1078.         }
  1079.     else
  1080.         {
  1081.         if ((intel(tp->acknum) == (s->seqnum + 1)) &&
  1082.             (intel(tp->seqnum) == s->acknum))
  1083.                 s->state = tcp_StateCLOSED;     /* no 2 msl */
  1084.         tcp_unthread(s);
  1085.         return (1);
  1086.         }
  1087.     break;
  1088.  
  1089.     case tcp_StateTIMEWT:
  1090.     s->flags = tcp_FlagACK;
  1091.     s->acknum = intel(tp->seqnum) + 1;
  1092.     tcp_send(s);
  1093.     break;
  1094.     }                        /* end switch */
  1095.     if (s->unhappy == TRUE) tcp_sendsoon(s);
  1096.     return (1);                    /* success */
  1097. }
  1098.  
  1099. /*
  1100.  * Process the data in an incoming packet.
  1101.  * Called from all states where incoming data can be received: established,
  1102.  * fin-wait-1, fin-wait-2
  1103.  */
  1104. static int
  1105. tcp_ProcessData(s, tp, len)
  1106. tcp_Socket *s;
  1107. tcp_Header *tp;
  1108. int len;
  1109. {
  1110.     register int diff, x;
  1111.     long ldiff;                    /* signed */
  1112.     byte *dp;
  1113.     word flags, *options, numoptions, opt_temp;
  1114.  
  1115.     if (s == NULL || tp == NULL) return (0);    /* failure */
  1116.  
  1117.     s->window = intel16(tp->window);
  1118.     flags = intel16(tp->flags);
  1119.     ldiff = s->acknum - intel(tp->seqnum);    /* signed long */
  1120.     if (flags & tcp_FlagSYN) ldiff--;    /* SYN counts as one unit */
  1121.     diff = ldiff;                /* 16 bit version */
  1122.  
  1123.                         /* find the data portion */
  1124.     x = tcp_GetDataOffset(tp) << 2;        /* quadword to byte format */
  1125.     dp = (byte *)tp + x;
  1126.  
  1127.                         /* process those options */
  1128.     if (numoptions = x - sizeof(tcp_Header))
  1129.         {
  1130.         options = (word *)(tp + sizeof(tcp_Header));
  1131.         while (numoptions-- > 0)
  1132.             switch (*options++)
  1133.                 {
  1134.                 case 0: numoptions = 0;    /* end of options */
  1135.                 case 1: break;        /* nop */
  1136.  
  1137.                   /* we are very liberal on MSS stuff */
  1138.                 case 2: if (*options == 2)
  1139.                         {
  1140.                 opt_temp = intel16(*(word*)(&options[1]));
  1141.                         if (opt_temp < s->mss)
  1142.                             s->mss = opt_temp;
  1143.                         }
  1144.                     numoptions -= 2 + *options;
  1145.                     options += *options;
  1146.                       break;
  1147.                 }    /* end of switch and while */
  1148.         }            /* end of if */
  1149.                     /* done option processing */
  1150.  
  1151.     len -= x;            /* remove the header length */
  1152.     if (diff >= 0)            /* skip already received bytes */
  1153.         {
  1154.         dp += diff;
  1155.         len -= diff;
  1156.  
  1157.         if (s->dataHandler != NULL)
  1158.             s->acknum += s->dataHandler(s, dp, len);
  1159.         else
  1160.     /* no handler, just dump to buffer, should be indexed, handles goofs */
  1161.                     /* limit receive size to our window */
  1162.             if (s->rdatalen >= 0)
  1163.                 {
  1164.                 if (len > (x = tcp_MaxBufSize - s->rdatalen))
  1165.                     len = x;
  1166.                 if (len > 0)
  1167.                     {  /* new ack begins at end of data */
  1168.                     s->acknum += len;
  1169.                     bcopy(dp, &s->rdata[s->rdatalen], len);
  1170.                     s->rdatalen += len;
  1171.                     }
  1172.                 }    /* end of  if (s->datalen.. else */
  1173.         }                /* end of if (diff > 0) */
  1174.     s->unhappy = (s->datalen != 0)? TRUE: FALSE;
  1175.  
  1176.     if (flags & tcp_FlagFIN)
  1177.         {
  1178.         s->acknum++;
  1179.         switch (s->state)
  1180.             {
  1181.                 case tcp_StateESTAB:
  1182.                 s->err_msg = "Connection closed.";
  1183.                             /* tcp_StateCLOSWT ... here we go */
  1184.                 x = tcp_StateLASTACK;
  1185.                 s->flags |= tcp_FlagFIN;
  1186.                 s->unhappy = TRUE;    /* to send packet */
  1187.                 break;
  1188.  
  1189.             case tcp_StateFINWT1:    /* on ack should go to finwt2 */
  1190.                 s->flags |= tcp_FlagFIN;
  1191.                     /* not certain of this addition */
  1192.                 x = tcp_StateCLOSING;
  1193.                 break;
  1194.  
  1195.                 case tcp_StateFINWT2:
  1196.                 x = tcp_StateTIMEWT;
  1197.                 break;
  1198.             }            /* end of switch (s->state) */
  1199.         s->state = x;
  1200.         }            /* end of if (flags & tcp_FlagFIN) */
  1201.     s->timeout = set_timeout(tcp_TIMEOUT);
  1202.     return (1);                /* success */
  1203. }
  1204.  
  1205. /*
  1206.  * Format and send an outgoing segment
  1207.  */
  1208. static int
  1209. tcp_send(s)
  1210. tcp_Socket *s;
  1211. {
  1212.     tcp_PseudoHeader ph;
  1213.     struct pkt
  1214.         {
  1215.         in_Header in;
  1216.         tcp_Header tcp;
  1217.         word maxsegopt[2];
  1218.         } register *pkt;
  1219.     byte *dp;
  1220.     int senddatalen, sendtotlen, sendpktlen;
  1221.     register int ippkt;                /* 1..s->cwindow */
  1222.  
  1223.     if (s == NULL) return (0);        /* failure */
  1224.  
  1225.     pkt = (struct pkt *)eth_formatpacket(&s->hisethaddr[0], 0x0008);
  1226.     dp = (byte *)pkt->maxsegopt;  /* dp constant for multi-packet sends */
  1227.  
  1228.                     /* this is our total possible send size */
  1229.     if (s->window > 0)
  1230.         senddatalen = (s->datalen >= s->window)? 
  1231.             s->window - 1: s->datalen;
  1232.     else    senddatalen = 0;
  1233.  
  1234.     sendtotlen = 0;            /* running count of what we've sent */
  1235.  
  1236.                     /* step through our packets */
  1237.     for (ippkt = 1; ippkt <= s->cwindow; ippkt++)
  1238.         {            /* adjust size for each packet */
  1239.             if (senddatalen > s->mss)
  1240.             senddatalen = s->mss;
  1241.                     /* tcp header */
  1242.             pkt->tcp.srcPort = intel16(s->myport);
  1243.             pkt->tcp.dstPort = intel16(s->hisport);
  1244.             pkt->tcp.seqnum = intel(s->seqnum + sendtotlen);
  1245.             pkt->tcp.acknum = intel(s->acknum);
  1246.             pkt->tcp.window = intel16(s->rmaxdatalen - s->rdatalen);
  1247.             pkt->tcp.flags = intel16(s->flags | 0x5000);
  1248.             pkt->tcp.checksum = 0;
  1249.             pkt->tcp.urgentPointer = 0;
  1250.  
  1251.                 /* do options if this is our first packet */
  1252.             if ((s->flags & (tcp_FlagSYN | tcp_FlagACK)) == tcp_FlagSYN)
  1253.             {
  1254.             sendpktlen = sizeof(tcp_Header) + 
  1255.                     sizeof(in_Header) + 4;
  1256.             pkt->tcp.flags = intel16(intel16(pkt->tcp.flags) +
  1257.                      0x1000);
  1258.             pkt->maxsegopt[0] = 0x0402;
  1259.             pkt->maxsegopt[1] = intel16(s->mss);
  1260.             dp += 4;
  1261.             }
  1262.         else
  1263.             {    
  1264.             if (senddatalen > 0)    /* handle packets with data */
  1265.                 {
  1266.                         sendpktlen = senddatalen + sizeof(tcp_Header)
  1267.                     + sizeof(in_Header);
  1268.                         bcopy(s->data, dp, senddatalen);
  1269.                 }
  1270.             else    /* handle no-data, not-first-SYN packets */
  1271.                     sendpktlen = sizeof(tcp_Header) + sizeof(in_Header);
  1272.                 }
  1273.  
  1274.                     /* internet header */
  1275.         pkt->in.hdrlen_ver = 0x45;    /* version 4, hdrlen 5 */
  1276.             pkt->in.tos = 0;
  1277.             pkt->in.identification = intel16(++ip_id); /* pre-inc req'd */
  1278.             pkt->in.frag = 0;
  1279. #ifdef KERMIT
  1280.             pkt->in.ttl = 60;
  1281. #else
  1282.             pkt->in.ttl = 254;
  1283. #endif
  1284.         pkt->in.proto = TCP_PROTO;
  1285.             pkt->in.checksum = 0;
  1286.             pkt->in.source = intel(my_ip_addr);
  1287.             pkt->in.destination = intel(s->hisaddr);
  1288.             pkt->in.length = intel16(sendpktlen);
  1289.  
  1290.             pkt->in.checksum = ~checksum(&pkt->in, sizeof(in_Header));
  1291.  
  1292.             /* compute tcp checksum */
  1293.             ph.src = pkt->in.source;   /* already in network order */
  1294.             ph.dst = pkt->in.destination;
  1295.             ph.mbz = 0;
  1296.             ph.protocol = 6;
  1297.             ph.length = intel16(sendpktlen - sizeof(in_Header));
  1298.             ph.checksum = checksum(&pkt->tcp,
  1299.                 (sendpktlen - sizeof(in_Header) + 1) & 0xfffe);
  1300.             pkt->tcp.checksum = ~checksum(&ph, sizeof(ph));
  1301.  
  1302. #ifdef DEBUG
  1303.             if (dbugxmit) (*dbugxmit)(s, &pkt->in, &pkt->tcp);
  1304. #endif
  1305.             if (eth_send(intel16(pkt->in.length)) == 0)
  1306.             return (0);            /* sending failed */
  1307.             sendtotlen += senddatalen;
  1308.     }                    /* do next ip pkt */
  1309.     if (s->karn_count == 2)
  1310.         {
  1311.             if (s->rto) s->rto = (s->rto * 3) / 2;
  1312.         else s->rto = 4;
  1313.             }
  1314.     else
  1315.             {
  1316.         s->vj_last = set_ttimeout(0);
  1317.         s->karn_count = 0;
  1318.         }
  1319.     s->rtt_time = set_ttimeout(s->rto);
  1320.     return (1);                    /* success */
  1321. }
  1322. /*
  1323.  * Format and send a reset tcp packet
  1324.  */
  1325. int
  1326. tcp_rst(in_Header *his_ip, tcp_Header *oldtcpp)
  1327. {
  1328.     tcp_PseudoHeader ph;
  1329.     struct pkt
  1330.         {
  1331.             in_Header in;
  1332.             tcp_Header tcp;
  1333.         word maxsegopt[2];
  1334.         } register *pkt;
  1335.  
  1336.     eth_Header *eth;
  1337.     register int sendtotlen;            /* length of packet */
  1338.  
  1339.     if (his_ip == NULL || oldtcpp == NULL) return (0);    /* failure */
  1340.  
  1341.                     /* see RFC 793 page 65 for details */
  1342.     if (oldtcpp->flags & tcp_FlagRST)
  1343.         return (0);  
  1344.     if ((oldtcpp->flags & tcp_FlagACK) == 0)
  1345.         {
  1346.             oldtcpp->seqnum = 0;
  1347.             oldtcpp->flags = tcp_FlagACK;
  1348.         }
  1349.     else
  1350.             oldtcpp->flags = 0;
  1351.  
  1352.     /* convoluted mechanism - reads his ethernet address or garbage */
  1353.     eth = eth_hardware((byte *)his_ip);
  1354.  
  1355.     pkt = (struct pkt *)eth_formatpacket(eth, 0x0008);
  1356.     sendtotlen = sizeof(tcp_Header) + sizeof(in_Header);
  1357.     pkt->in.length = intel16(sendtotlen);
  1358.                     /* TCP header */
  1359.     pkt->tcp.srcPort = oldtcpp->dstPort;
  1360.     pkt->tcp.dstPort = oldtcpp->srcPort;
  1361.     pkt->tcp.seqnum = oldtcpp->seqnum;
  1362.     pkt->tcp.acknum = oldtcpp->acknum;
  1363.     pkt->tcp.window = 0;
  1364.     pkt->tcp.flags = tcp_FlagRST | oldtcpp->flags;
  1365.     pkt->tcp.checksum = 0;
  1366.     pkt->tcp.urgentPointer = 0;
  1367.                     /* Internet header */
  1368.     pkt->in.hdrlen_ver = 0x45;        /* version 4, hdrlen 5 */
  1369.     pkt->in.tos = 0;
  1370.     pkt->in.identification = intel16(++ip_id); /* use pre-inc here */
  1371.     pkt->in.frag = 0;
  1372. #ifdef KERMIT
  1373.     pkt->in.ttl = 60;            /* time to live */
  1374. #else
  1375.     pkt->in.ttl = 254;
  1376. #endif
  1377.     pkt->in.proto = TCP_PROTO;
  1378.     pkt->in.checksum = 0;
  1379.     pkt->in.source = his_ip->destination;
  1380.     pkt->in.destination = his_ip->source;
  1381.     pkt->in.checksum = ~checksum(&pkt->in, sizeof(in_Header));
  1382.                         /* compute TCP checksum */
  1383.     ph.src = pkt->in.source;        /* already big endian */
  1384.     ph.dst = pkt->in.destination;
  1385.     ph.mbz = 0;
  1386.     ph.protocol = 6;
  1387.     ph.length = intel16(sendtotlen - sizeof(in_Header));
  1388.     ph.checksum = checksum(&pkt->tcp, (sendtotlen - sizeof(in_Header) + 1)
  1389.                                 & 0xfffe);
  1390.     pkt->tcp.checksum = ~checksum(&ph, sizeof(ph));
  1391.  
  1392. #ifdef DEBUG
  1393.     if (dbugxmit) (*dbugxmit)(NULL, &pkt->in, &pkt->tcp);
  1394. #endif
  1395.     return (eth_send(intel16(pkt->in.length)));
  1396. }
  1397.  
  1398.  
  1399. /**********************************************************************
  1400.  * socket functions
  1401.  **********************************************************************/
  1402.  
  1403. /* socket based procedures */
  1404.  
  1405. /*
  1406.  * sock_yield - enable user defined yield function
  1407.  */
  1408. void
  1409. sock_yield(tcp_Socket *s, void (*fn)())
  1410. {
  1411.     if (s != NULL)
  1412.         s->usr_yield = fn;
  1413.     else
  1414.         system_yield = fn;
  1415. }
  1416.  
  1417. /*
  1418.  * sock_mode - set binary or ascii - affects sock_gets, sock_dataready
  1419.  *         - set udp checksums
  1420.  */
  1421. int
  1422. sock_mode(tcp_Socket *s, word mode)
  1423. {
  1424.     if (s != NULL)
  1425.         {
  1426.         s->soc_mode = (s->soc_mode & 0xfffc) | mode;
  1427.         return (1);        /* success */
  1428.         }
  1429.     else
  1430.         return (0);        /* failure */
  1431. }
  1432.  
  1433. /*
  1434.  * sock_read - read a socket with maximum n bytes
  1435.  *         - busywaits until buffer is full but calls s->usr_yield
  1436.  *         - returns count also when connection gets closed
  1437.  */
  1438. int
  1439. sock_read(sock_type *s, byte *dp, int len)
  1440. {
  1441.     register int templen, count;
  1442.     count = 0;
  1443.  
  1444.     if (s == NULL || dp == NULL) return (0);        /* failure */
  1445.     do
  1446.             {
  1447.         if (s->udp.ip_type == UDP_PROTO)
  1448.             templen = udp_read(s, dp, len);
  1449.         else
  1450.             templen = tcp_read(s, dp, len);
  1451.         if (templen = 0)
  1452.             if (tcp_tick(s) == 0) return (count);
  1453.         if (s->tcp.usr_yield != NULL) (s->tcp.usr_yield)();
  1454.         count += templen;
  1455.         len -= templen;
  1456.             }
  1457.     while (len > 0);
  1458.        return (count);
  1459. }
  1460.  
  1461. /*
  1462.  * sock_fastread - read a socket with maximum n bytes
  1463.  *         - does not busywait until buffer is full
  1464.  */
  1465. int
  1466. sock_fastread(sock_type *s, byte *dp, int len)
  1467. {
  1468.     if (s == NULL || dp == NULL) return (0);    /* failure */
  1469.     if (s->udp.ip_type == UDP_PROTO)
  1470.         len = udp_read(s, dp, len);
  1471.     else
  1472.         len = tcp_read(s, dp, len);
  1473.     return (len);
  1474. }
  1475.  
  1476.  
  1477. /*
  1478.  * sock_write - writes data and returns length written
  1479.  *          - does not perform flush
  1480.  *          - repeatedly calls s->usr_yield
  1481.  */
  1482. int
  1483. sock_write(sock_type *s, byte *dp, int len)
  1484. {
  1485.     register int offset, oldlen;
  1486.  
  1487.     oldlen = len;
  1488.     offset = 0;
  1489.     if (s == NULL || dp == NULL) return (0);    /* failure */
  1490.     while (len  > 0)
  1491.         {
  1492.         if (s->udp.ip_type == UDP_PROTO)
  1493.             offset += udp_Write(s, dp + offset, len);
  1494.         else
  1495.             offset += tcp_Write(s, dp + offset, len);
  1496.         len = oldlen - offset;
  1497.         if (s->udp.usr_yield != NULL) (s->udp.usr_yield)();
  1498.         if (tcp_tick(s) == 0) return (0);    /* no socket */
  1499.         }
  1500.     return (oldlen);
  1501. }
  1502.  
  1503. int
  1504. sock_fastwrite(sock_type *s, byte *dp, int len)
  1505. {
  1506.     tcp_tick(NULL);                /* updates our output buffer*/
  1507.     if (s == NULL) return (0);        /* failure */
  1508.  
  1509.     return ((s->udp.ip_type == UDP_PROTO)? 
  1510.         udp_Write(s, dp, len):
  1511.         tcp_Write(s, dp, len));
  1512. }
  1513.  
  1514. int
  1515. sock_flush(sock_type *s)
  1516. {
  1517.     if (s == NULL) return (0);            /* failure */
  1518.     if (s->tcp.ip_type == TCP_PROTO)
  1519.         tcp_Flush(s);
  1520.     return (1);
  1521. }
  1522. /*
  1523.  * sock_flushnext - cause next transmission to have a flush
  1524.  */
  1525. int
  1526. sock_flushnext(sock_type *s)
  1527. {
  1528.     if (s == NULL) return (0);            /* failure */
  1529.     if (s->tcp.ip_type == TCP_PROTO)
  1530.         s->tcp.flags |= tcp_FlagPUSH;
  1531.     return (1);                    /* success */
  1532. }
  1533. /*
  1534.  * sock_putc - put a character
  1535.  *         - no expansion but flushes on '\n'
  1536.  *         - returns character
  1537.  */
  1538. int
  1539. sock_putc(sock_type *s, byte c)
  1540. {
  1541.     byte ch;
  1542.  
  1543.     ch = c;
  1544.     if (s == NULL) return (-1);            /* failure */
  1545.     if ((ch == '\n') || (ch == '\r'))
  1546.         sock_flushnext(s);
  1547.     sock_write(s, &ch, 1);
  1548.     return (ch & 0xff);
  1549. }
  1550.  
  1551. int
  1552. sock_getc(sock_type *s)
  1553. {
  1554.     byte ch;
  1555.  
  1556.     if (s == NULL) return (-1);            /* failure */
  1557.     sock_read(s, &ch, 1);
  1558.     return (ch & 0xff);
  1559. }
  1560.  
  1561. #ifndef KERMIT
  1562. /*
  1563.  * sock_puts - does not append carriage return in binary mode
  1564.  *         - returns length
  1565.  */
  1566. int
  1567. sock_puts(sock_type *s, byte *dp)
  1568. {
  1569.     register int len;
  1570.  
  1571.     if (s == NULL || dp == NULL) return (0);    /* failure */
  1572.  
  1573.     len = strlen(dp);
  1574.     sock_flushnext(s);
  1575.     sock_write(s, dp, len);
  1576.     if (s->tcp.soc_mode & TCP_MODE_ASCII)
  1577.         sock_putc(s, '\n');
  1578.     return (len);
  1579. }
  1580. #endif    /* KERMIT */
  1581.  
  1582. /*
  1583.  * sock_update - update the socket window size to the other guy
  1584.  * Note: a better and safer criterion is s->rdatalen < mss
  1585.  *  which allows room for a full incoming segment without loss or overflow.
  1586.  */
  1587. static int
  1588. sock_update(tcp_Socket *s)
  1589. {
  1590.     if (s == NULL) return (0);            /* failure */
  1591.     if (s->ip_type == TCP_PROTO)
  1592.         {
  1593.         if (s->rdatalen < (3 * s->rmaxdatalen) / 4)
  1594.             tcp_send(s);        /* update the window */
  1595.         else
  1596.             tcp_sendsoon(s);
  1597.         }
  1598.     return (1);                    /* success */
  1599. }
  1600. #ifndef KERMIT
  1601. /*
  1602.  * sock_gets - read a string from any socket
  1603.  *         - return length of returned string
  1604.  *         - removes end of line terminator
  1605.  */
  1606. word 
  1607. sock_gets(sock_type *s, byte *dp, int n)
  1608. {
  1609.     int len, templen;
  1610.     byte *src_p, *temp, *temp2;
  1611.     word *np;
  1612.  
  1613.  
  1614.     if (s == NULL || dp == NULL) return (0);        /* failure */
  1615.  
  1616.     if (s->udp.ip_type == UDP_PROTO) {
  1617.         if (n > udp_MaxBufSize) n = udp_MaxBufSize;
  1618.     src_p = s->udp.rdata;
  1619.     np = &s->udp.rdatalen;
  1620.     } else {
  1621.        if (n > tcp_MaxBufSize) n = tcp_MaxBufSize;
  1622.     src_p = s->tcp.rdata;
  1623.     np = &s->tcp.rdatalen;
  1624.     }
  1625.  
  1626.     src_p[ *np ] = 0;         /* terminate string */
  1627.     strncpy(dp, src_p, n);    /* copy everything */
  1628.     dp[ n-1 ] = 0;        /* terminate */
  1629.  
  1630.     if (temp = strchr(dp, '\n')) *temp = 0;
  1631.     if (temp2= strchr(dp, '\r')) *temp2= 0;
  1632.     len = strlen(dp);
  1633.  
  1634.                 /* skip if there were no crs or lfs ??? */
  1635.     if ((temp2 == NULL) && (temp == NULL) && (strlen(dp) < n - 1)) {
  1636.     *dp = 0;
  1637.     return (0);
  1638.     }
  1639.  
  1640.                 /* skip over \n and \r but stop on end */
  1641. #ifndef OLD
  1642.     if (temp) templen = temp - (byte *)dp;
  1643.     else if (temp2) templen = temp2 - (byte *)dp;
  1644.     else templen = len + 1;
  1645.  
  1646.     if (templen) {
  1647.         templen++;
  1648.         bcopy(&src_p[ templen ], src_p, *np -= templen);
  1649.     } else
  1650.         *np = 0;
  1651. #else
  1652.     temp = &src_p[ len + 1 ];
  1653.     while (*temp && ((*temp == '\n') || (*temp == '\r')))
  1654.     temp++;
  1655.  
  1656.     if (*temp)
  1657.     bcopy(temp, src_p, *np = strlen(temp));
  1658.     else
  1659.     *np = 0;
  1660. #endif /* OLD */
  1661.  
  1662.     sock_update((tcp_Socket *)s);    /* new window */
  1663.     return (len);
  1664. }
  1665. #endif    /* KERMIT */
  1666.  
  1667. /*
  1668.  * sock_dataready - returns number of bytes waiting to be read
  1669.  *          - if in ASCII mode, return 0 until a line is present
  1670.  *            or the buffer is full
  1671.  */
  1672. word 
  1673. sock_dataready(sock_type *s)
  1674. {
  1675.     register int len;
  1676.     register byte *p;
  1677.  
  1678.     if (s == NULL) return (0);            /* failure */
  1679.     if ((len = s->tcp.rdatalen) == 0) return (0);
  1680.  
  1681.     if (s->tcp.soc_mode & TCP_MODE_ASCII)
  1682.         {
  1683.         if (len == tcp_MaxBufSize)
  1684.             return (tcp_MaxBufSize);
  1685.                 /* check for terminating \n \r */
  1686.         p = s->tcp.rdata;
  1687.         if ((strchr(p, '\n') == NULL) || (strchr(p, '\r') == NULL))
  1688.             return (len);
  1689.         return (0);
  1690.         }
  1691.         return (len);
  1692. }
  1693.  
  1694. int
  1695. sock_established(sock_type *s)
  1696. {
  1697.     if (s == NULL) return (0);            /* failure */
  1698.     switch (s->tcp.ip_type)
  1699.         {
  1700.         case UDP_PROTO:
  1701.             return (1);
  1702.         case TCP_PROTO:
  1703.             return (s->tcp.state == tcp_StateESTAB);
  1704.         default:
  1705.             return (0);
  1706.         }
  1707. }
  1708.  
  1709. int
  1710. sock_close(s)
  1711. sock_type *s;
  1712. {
  1713.     register int status;
  1714.  
  1715.     if (s == NULL) return (0);            /* failure */
  1716.     switch (s->udp.ip_type)
  1717.         {
  1718.         case UDP_PROTO :
  1719.             status = udp_close(s);
  1720.             break;
  1721.         case TCP_PROTO :
  1722.             status = tcp_close(s);
  1723.             tcp_tick(s);
  1724.             break;
  1725.         }
  1726.     return (status);                    /* success */
  1727. }
  1728.  
  1729. /* return count of chars in socket receive buffer which lie before char ch */
  1730. word
  1731. sock_findch(sock_type *s, byte ch)
  1732. {
  1733.     int i;
  1734.     int len;
  1735.     register byte c = ch;
  1736.     register byte * p;
  1737.  
  1738.     tcp_tick(s);                /* update socket buffer */
  1739.     if ((len = sock_dataready(s)) == 0)    /* get qty available */
  1740.         return (-1);            /* say no char available */
  1741.     p = s->tcp.rdata;        /* point to start of socket buffer */
  1742.     for (i = 0; i < len; i++)        /* scan for byte ch */
  1743.         if (*p++ == ch) break;        /* stop when found */
  1744.     return (i);
  1745. }
  1746.     
  1747.  
  1748. /*
  1749.  * ip user level timer stuff
  1750.  *   void ip_timer_init(void *s, int delayseconds)
  1751.  *   int  ip_timer_expired(void *s)
  1752.  *    - 0 if not expired
  1753.  */
  1754.  
  1755.  
  1756. void 
  1757. ip_timer_init(s, delayseconds)
  1758. udp_Socket *s;
  1759. int delayseconds;
  1760. {
  1761.     if (s == NULL)
  1762.         return;
  1763.     if (delayseconds != 0)
  1764.         s->usertimer = set_timeout(delayseconds);
  1765.     else
  1766.         s->usertimer = 0;
  1767. }
  1768.  
  1769. int 
  1770. ip_timer_expired(s)
  1771. udp_Socket *s;
  1772. {
  1773.     if (s == NULL) return (1);            /* say time out */
  1774.     if (s->usertimer == 0)                /* cannot expire */
  1775.         return (0);
  1776.  
  1777.     return (chk_timeout(s->usertimer));
  1778. }
  1779.  
  1780. long 
  1781. make_timeout(word timeout)
  1782. {
  1783.     if (timeout) return (set_timeout(timeout));
  1784.     return (0);
  1785. }
  1786.  
  1787. /*
  1788.  * check_timeout - test agains timeout clock - account for overflow
  1789.  */
  1790. int 
  1791. check_timeout(unsigned long timeout)
  1792. {
  1793.     if (timeout) return (chk_timeout(timeout));
  1794.     return (0);
  1795. }
  1796.  
  1797. /*
  1798.  * ip_delay0 called by macro sock_wait_established()
  1799.  * ip_delay1 called by macro sock_wait_intput()
  1800.  * ip_delay2 called by macro sock_wait_closed();
  1801.  *
  1802.  */
  1803.  
  1804. ip_delay0(s, timeoutseconds, fn, statusptr)
  1805. sock_type *s;
  1806. int timeoutseconds;
  1807. procref fn;
  1808. int *statusptr;
  1809. {
  1810.     register int status;
  1811.  
  1812.     if (s == NULL)
  1813.         {
  1814.         status = -1;        /* failure */
  1815.             if (statusptr != NULL) *statusptr = status;
  1816.         return (status);
  1817.         }
  1818.     ip_timer_init(s, timeoutseconds);
  1819.  
  1820.     do
  1821.         {
  1822.         if (s->tcp.ip_type == TCP_PROTO)
  1823.             if (tcp_established(s))
  1824.                 {
  1825.                 status = 0;
  1826.                 break;
  1827.                 }
  1828.  
  1829.         if (tcp_tick(s) == 0)
  1830.             {
  1831.             s->tcp.err_msg = "Host refused connection";
  1832.             status = -1;    /* get an early reset */
  1833.             break;
  1834.             }
  1835.  
  1836.         if (ip_timer_expired(s))
  1837.             {
  1838.             sock_close(s);
  1839.             status = -1;
  1840.             break;
  1841.             }
  1842.         if (fn != NULL) if (status = fn(s)) break;
  1843.         if (s->tcp.usr_yield != NULL) (s->tcp.usr_yield)();
  1844.         if (s->tcp.ip_type == UDP_PROTO)
  1845.             {
  1846.             status = 0;
  1847.             break;
  1848.             }
  1849.         } while (1 == 1);
  1850.     if (statusptr != NULL) *statusptr = status;
  1851.     return (status);
  1852. }
  1853.  
  1854. int
  1855. ip_delay1(s, timeoutseconds, fn, statusptr)
  1856. sock_type *s;
  1857. int timeoutseconds;
  1858. procref fn;
  1859. int *statusptr;
  1860. {
  1861.     register int status;
  1862.  
  1863.     if (s == NULL)
  1864.         {
  1865.         status = -1;        /* failure */
  1866.             if (statusptr != NULL) *statusptr = status;
  1867.         return (status);
  1868.         }
  1869.  
  1870.     ip_timer_init(s, timeoutseconds);
  1871.     sock_flush(s);        /* new enhancement */
  1872.  
  1873.     do
  1874.         {
  1875.         if (sock_dataready(s))
  1876.             {
  1877.             status = 0;
  1878.             break;
  1879.             }
  1880.  
  1881.         if (tcp_tick(s) == 0)
  1882.             {
  1883.             status = 1;
  1884.             break;
  1885.             }
  1886.         if (ip_timer_expired(s))
  1887.             {
  1888.             sock_close(s);
  1889.             status = -1;
  1890.             break;
  1891.             }
  1892.         if (fn != NULL)
  1893.             if (status = fn(s)) break;
  1894.         if (s->tcp.usr_yield != NULL) (s->tcp.usr_yield)();
  1895.         } while (1 == 1);
  1896.  
  1897.     if (statusptr != NULL) *statusptr = status;
  1898.     return (status);
  1899. }
  1900.  
  1901. int
  1902. ip_delay2(s, timeoutseconds, fn, statusptr)
  1903. sock_type *s;
  1904. int timeoutseconds;
  1905. procref fn;
  1906. int *statusptr;
  1907. {
  1908.     register int status;
  1909.  
  1910.     if (s == NULL)
  1911.         {
  1912.         status = 0;        /* failure */
  1913.             if (statusptr != NULL) *statusptr = status;
  1914.         return (status);
  1915.         }
  1916.  
  1917.     ip_timer_init(s, timeoutseconds);
  1918.  
  1919.     if (s->tcp.ip_type != TCP_PROTO) return (1);
  1920.  
  1921.     do
  1922.         {
  1923.         if (tcp_tick(s) == 0)        /* 0 means no socket */
  1924.             {
  1925.             status = 1;
  1926.             break;
  1927.             }
  1928.         if (ip_timer_expired(s))
  1929.             {
  1930.             sock_abort(s);
  1931.             status = 0;
  1932.             break;
  1933.             }
  1934.         if (fn != NULL)
  1935.             if (status = fn(s)) break;
  1936.         if (s->tcp.usr_yield != NULL) (s->tcp.usr_yield)();
  1937.         } while (1 == 1);
  1938.  
  1939.     if (statusptr != NULL) *statusptr = status;
  1940.     return (status);
  1941. }
  1942.  
  1943.  
  1944. byte *
  1945. rip(byte *s)    /* put null terminator on CR or LF */
  1946. {
  1947.     register byte *temp;
  1948.  
  1949.     if (s == NULL) return (NULL);            /* failure */
  1950.     if (temp = strchr(s, '\n')) *temp = 0;
  1951.     if (temp = strchr(s, '\r')) *temp = 0;
  1952.     return (s);
  1953. }
  1954.  
  1955.